package com.github.boxuanjia.toycar;

import com.github.boxuanjia.toycar.cache.DiskCache;
import com.github.boxuanjia.toycar.cache.DiskLruCacheWrapper;
import com.github.boxuanjia.toycar.util.Util;
import ohos.agp.components.ComponentProvider;
import ohos.agp.components.Image;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.media.image.ImagePacker;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class ToyCar {

    private static DiskCache diskCache;
    private static EventHandler workHandler;

    public static void initialize(Context context) {
        diskCache = DiskLruCacheWrapper.get(getPhotoCacheDir(context, "image_manager_disk_cache"), 700 * 1024 * 1024);
        workHandler = new EventHandler(EventRunner.create());
    }

    public static Request load(String string) {
        return new Request(string);
    }

    public static class Request {

        private String url;

        public Request(String url) {
            this.url = url;
        }

        public void into(Image imageView) {
            workHandler.postTask(()-> {
                PixelMap pixelMap = doInto();
                if (pixelMap!=null) {
                    imageView.getContext().getUITaskDispatcher().syncDispatch(()-> {
                        imageView.setPixelMap(pixelMap);
                    });
                }
            });
        }

        public void into(ComponentProvider componentProvider, int imageId) {
            PixelMap pixelMap = doInto();
            if (pixelMap!=null) {
                componentProvider.setImagePixelMap(imageId, pixelMap);
            }
        }

        public PixelMap doInto() {
            PixelMap pixelMap;
            InputStream is = diskCache.get(generateSafeKey(url));
            if (is != null) {
                ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
                ImageSource imageSource = ImageSource.create(is, srcOpts);
                if (imageSource != null) {
                    pixelMap = imageSource.createPixelmap(null);
                    if (pixelMap == null) {
                        diskCache.delete(generateSafeKey(url)); //the image must have been corrupted
                    } else {
                        return pixelMap;
                    }
                }
            }

            pixelMap = downLoad();
            if (pixelMap!=null) {
                PixelMap finalPixelMap = pixelMap;
                diskCache.put(generateSafeKey(url), os -> {
                    ImagePacker imagePacker = ImagePacker.create();
                    ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
                    packingOptions.format = "image/jpeg";
                    imagePacker.initializePacking(os, packingOptions);
                    imagePacker.addImage(finalPixelMap);
                    imagePacker.finalizePacking();
                });
            }
            return pixelMap;
        }

        private PixelMap downLoad() {
            HttpURLConnection connection = null;
            try {
                URLConnection urlConnection = new URL(url).openConnection();
                if (urlConnection instanceof HttpURLConnection) {
                    connection = (HttpURLConnection) urlConnection;
                }
                if (connection != null) {
                    connection.connect();

                    InputStream inputStream = urlConnection.getInputStream();
                    ImageSource imageSource = ImageSource.create(inputStream,
                            new ImageSource.SourceOptions());
                    ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
                    decodingOptions.desiredPixelFormat = PixelFormat.ARGB_8888;
                    PixelMap pixelMap = imageSource.createPixelmap(decodingOptions);

                    return pixelMap;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    }



    private static File getPhotoCacheDir(Context context, String cacheName) {
        File cacheDir = context.getFilesDir();
        if (cacheDir != null) {
            File result = new File(cacheDir, cacheName);
            result.mkdirs();
            return result;
        }
        return null;
    }

    private static String generateSafeKey(String url) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(url.getBytes("UTF-8"));
            return Util.sha256BytesToHex(messageDigest.digest());
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return url;
    }
}
